<?php
declare(strict_types=1);

namespace ServerApp\lib\server\conf;

use ServerApp\lib\core\ServerType;
use ServerApp\lib\server\model\redis\ConfClient;
use ServerApp\lib\server\model\swoole\FdList;
use function test\io\co\server;

//use ServerApp\lib\server\udp\Udp;
//use Swoole\Coroutine\Client;
//use WebApp\lib\db\UdpClientPool;

/**
 * Class ConfStation
 * @package server\lib
 */
class ConfStation
{
    const SPLIT = "^";
    const SERVERS = 'a';
    const SWITCH = 'b';

    private $udp_server_set = [];

    /**
     * ConfStation constructor.
     */
    private function __construct()
    {
    }

    private static $instance = null;

    public static function getInstance(){
        if(self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * @param string $data
     * @param string $fd
     */
    public function decodeMsg(string $data, string $fd)
    {
        $arr = explode(ConfStation::SPLIT, $data);
        $cmd = array_shift($arr);
        if($cmd == 0){
            list($type, $host, $worker_id, $server_name) = $arr;
            $this->addServer($fd, $host, $type, $worker_id, $server_name);
        }
    }

    /**
     * @param string $fd
     * @param $host
     * @param $type
     * @param $worker_id
     * @param $server_name
     * @internal param $arr
     */
    private function addServer(string $fd, $host, $type, $worker_id, $server_name){
        list($ip, $port) = explode(":", $host);
        if (!isset($this->udp_server_set[$ip] )) {
            $this->udp_server_set[$ip] = [];
        }
        $this->udp_server_set[$ip][(int)$port] = null;

        ConfClient::getInstance()->hSet($host, $type);
        FdList::getInstance()->setRow($fd, [
            FdList::DEVICE=> "$host|$type|$worker_id|$server_name"
        ]);
        switch (intval($type)) {
            case ServerType::SERVER:
                $this->changeServer();
                break;
            default:
//                self::changeServer($server, $fd);
                break;
        }
    }

    /**
     * @param $all
     * @return array
     */
    private function getServers($all): array
    {
        $res = [];
        foreach ($all as $host => $type){
            $type = (int)$type;
            if ($type === ServerType::SERVER){
                $res[] = $host;
            }
        }
        return $res;
    }

    /**
     * @param string $fd
     */
    public function close(string $fd){
        $row = FdList::getInstance()->getRow($fd);
        FdList::getInstance()->getRow($fd);
        if ($row) {
            list($host, $type) = explode('|', $row[FdList::DEVICE]);

            ConfClient::getInstance()->hDel($host);
            if($type == ServerType::SERVER){
                tracker(I, "close Client is server");
                $this->changeServer();
            } else {
                tracker(I, "Client is http");
            }

            list($ip, $port) = explode(":", $host);
            unset($this->udp_server_set[$ip][(int)$port]);
            if (count($this->udp_server_set[$ip]) <= 0) {
                unset($this->udp_server_set[$ip]);
            }
        }
    }

    private $servers;

    private function changeServer(){
        $servers = $this->getServers(ConfClient::getInstance()->hGetAll());
        $this->servers = $servers;
        tracker(D, $this->servers);
//        $str = join(Udp::SPLIT, [
//            ConfStation::SERVERS,
//            $servers ? json_encode($servers):'',
//        ]);
//
//        foreach ($this->udp_server_set as $ip => $arr){
//            UdpClientPool::getInstance("$ip:7788")->exec(function(Client $client) use ($str){
//                $client->send($str);
//            });
//        }
    }
}